#include <Arduino.h>
#include "CircularBuffer.h"
#include "I2CSlave.h"
#include "SWMonitor.h"

#include "DataStorage.h"
#include "DataStorageAddressableLed.h"

#include "CmdLine.h"
#include "TimeOut.h"
#include "LedController.h"

#include "DigitalOut.h"
#include "CD74HC4051.h"
#include "Multiplexers.h"
#include "log.h"
#include "lwmp.h"
#include "Ticker.h"
//"PD3",TIMER2B);
//"PB2",TIMER1B);
//"PD5",TIMER0B);
//"PB1",TIMER1A);
//"PB3",TIMER2A);
CmdLine cmdline;

Mail<> mb;

I2CSlave i2c_slave(mb);

AddressableLedData addressable_led_data(mb);

DataStorage dataStorage(&addressable_led_data);

SW1248 sw1248;

SWMonitor sw_monitor(sw1248);

Timeout data_monitor_timeout;

Timeout sw_monitor_timeout;

ti::CD74HC4051 mux0(PC_3,PD_2,PD_3,PD_4);
ti::CD74HC4051 mux1(PB_2,PC_0,PC_1,PC_2);
ti::CD74HC4051 mux2(PB_3,PD_5,PD_6,PB_1);

Multiplexers multiplexers(mux0,mux1,mux2);

LedController ledController(i2c_slave,dataStorage,multiplexers);

Scheduler* scheduler_tasks[]={
  &cmdline,             //添加任务0: 接收命令         (Y)
  &sw1248,              //添加任务1: 按键扫描         (Y)
  &sw_monitor,          //添加任务2: 按键状态检测     (Y)
  &ledController        //添加任务5: 系统控制         (Y)
};

//#include <wiring.c>
//#include "wiring_private.h"
// cbi(TIMSK0, TOIE0);
// sbi(TIMSK0, TOIE0);

volatile int cnt =0;


void setup() {

  // put your setup code here, to run once:

  // start serial for output 
  Serial.begin(9600);    
  log::debug("pro:WF1-Addressable_LED_3@%s-%s\r\n",__DATE__,__TIME__);

  
  // // start sw1248 
  sw1248.begin();
  log::debug("sw1248 begin:0x%x\r\n",sw1248.state().value);
  sw_monitor.attach([]{
    //检测到地址发生改变，设置超时后更新I2C地址
    sw_monitor_timeout.attach([]{
      i2c_slave.begin(sw1248.state().value);
      sw_monitor_timeout.detach();
      log::debug("i2c begin new addr:%x\r\n",sw1248.poll());
    },6000);
  });

  // mux0.test();
  // for(;;){
  //   delay(1000);
  // }
  // start data storage 
  dataStorage.begin();
  log::debug("ds begin:0x%x\r\n",dataStorage.read_data_storage_eof());

  // start i2c
  i2c_slave.begin(sw1248.state().value);
  log::debug("i2c begin:%x\r\n",sw1248.state().value);

  
  i2c_slave.on_request([]{
    //返回主机请求的数据
    data_storage_reg_read_t& reg = dataStorage.get_reg_data(i2c_slave.get_reg_read_address());
    i2c_slave.write((const uint8_t *)reg.data,reg.size);
  });

  i2c_slave.on_receive([](int howMany){
      //处理主机发送的数据
      i2c_slave.handle_on_receive(howMany);
      //30秒检测一次
      //data_monitor_timeout.attach(&dataStorage,&DataStorage::check_update,30000);
  });

  ledController.begin();
  log::debug("run tasks\r\n");
}

os::memory_pool_t::memory_node_t node;

void loop() {
  // put your main code here, to run repeatedly:
  for(uint8_t i=0;i<sizeof(scheduler_tasks)/sizeof(Scheduler*);i++){
    scheduler_tasks[i]->schedule();
  }
}

void serialEvent() {
  // 当接收到数据时，这个函数会被自动调用
  // cmdline.cleanup();
  // while (Serial.available()) {
  //   char inChar = (char)Serial.read(); // 读取一个字节的数据
  //   cmdline.append(inChar);
  // }
  // cmdline.update();
}